/**
 * User: alesj
 * Date: 2005.6.8
 * Time: 11:20:35
 * 
 * (C) Genera Lynx d.o.o.
 */

package com.generalynx.ecos.page;

import java.io.Serializable;
import java.text.MessageFormat;

import com.generalynx.common.utils.Tools;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;

public class AlphaPageScroll extends IndexPageScroll implements InitializingBean {

    private static final int DEFAULT_LENGTH = 1;

    private int length;
    private char[] availableChars = CharsConstants.CHARS;

    private String alphaProperty;
    private int step;
    private int taskbarSize;

    private AlphaHelper alphaHelper;
    private int size;

    protected AlphaPageScroll() {
        this(DEFAULT_LENGTH);    
    }
    
    protected AlphaPageScroll(int length) {
        this.length = length;
    }

    public AlphaPageScroll(int length, String alphaProperty) {
        this(length);
        this.alphaProperty = alphaProperty;
    }

    public AlphaPageScroll(int length, String alphaProperty, String code) {
        this(length);
        this.alphaProperty = alphaProperty;
        Constants constants = new Constants(CharsConstants.class);
        availableChars = (char[])constants.asObject(code);
    }

    public void afterPropertiesSet() throws Exception {
        if (getAlphaProperty() == null) {
            throw new IllegalArgumentException("AlphaProperty must be set!");
        }
        alphaHelper = AlphaHelper.getInstance(availableChars);
        size = alphaHelper.getSize(length);
        if (taskbarSize == 0) {
            taskbarSize = availableChars.length;
        }
        step = size / taskbarSize;
    }

    private char[] getChars(int index) {
        return alphaHelper.getChars(index, length);
    }

    public boolean isLimitable() {
        return false;
    }

    public Serializable getPreviousIdentifier() {
        return new Integer(currentIdentifier - step);
    }

    public Serializable getNextIdentifier() {
        return new Integer(currentIdentifier + step);
    }

    public boolean isUsePageScroll() {
        return true;
    }

    public boolean isLast() {
        return (currentIdentifier + step >= size);
    }

    public String doTaskbar() {
        int i = 0;
        StringBuffer buffer = new StringBuffer();
        while(i < size) {
            CharsKey ck = new CharsKey(getChars(i));
            if (i > 0) {
                buffer.append('.');
            }
            buffer.append(MessageFormat.format(i == currentIdentifier ? BOLD_PATTERN : LINK_PATTERN,
                                               new Object[]{Tools.strictCapitalize(ck.toString()),
                                                            new Integer(i)})
            );
            i+=step;
        }
        return buffer.toString();
    }

    public String query() {
        return select() + "from " + from() + " e" +
                " where upper(substring(e." + getAlphaProperty() + ", 1, " + length + ")) >= :fA" +
                (!isLast() ? " and upper(substring(e." + getAlphaProperty() + ", 1, " + length + ")) < :fB" : "");
    }

    public Object propertiesBean() {
        return (isLast()) ?
                new PropertyBean(new CharsKey(getChars(currentIdentifier))) :
                new PropertyBean(new CharsKey(getChars(currentIdentifier)),
                                 new CharsKey(getChars(currentIdentifier + step)));
    }

    public String orderBy() {
        return getAlphaProperty();
    }

    private class PropertyBean {
        private CharsKey fA;
        private CharsKey fB;

        public PropertyBean(CharsKey fA) {
            this.fA = fA;
        }

        public PropertyBean(CharsKey fA, CharsKey fB) {
            this(fA);
            this.fB = fB;
        }

        public String getfA() {
            return fA.toString().toUpperCase();
        }

        public String getfB() {
            return fB.toString().toUpperCase();
        }
    }

    public String getAlphaProperty() {
        return alphaProperty;
    }

    public void setAlphaProperty(String alphaProperty) {
        this.alphaProperty = alphaProperty;
    }

    public int getTaskbarSize() {
        return taskbarSize;
    }

    public void setTaskbarSize(int taskbarSize) {
        this.taskbarSize = taskbarSize;
    }

}
